﻿using Sl.Duplex;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Text;
using System.Threading.Tasks;

namespace ChholConfig {
	internal class SerialPortSelecter {
		public ComPortDesc[] Ports;
		public int Avaliable_port_num => Ports.Count(cpd => cpd.avaliable);

		public SerialPortSelecter() {
			var cpds = (from str in System.IO.Ports.SerialPort.GetPortNames()
					   select new ComPortDesc(str)).ToArray();
			getPortDeviceName(cpds);
			getAvaliablePort(cpds);
			Ports = cpds.OrderBy(cpd=>!cpd.avaliable).ToArray();
		}

		private void getPortDeviceName(IEnumerable<ComPortDesc> cpds) {
			List<string> device_names = new List<string>(128);

			using (ManagementObjectSearcher searcher = new ManagementObjectSearcher
			("select * from Win32_PnPEntity where Name like '%(COM%'")) {
				foreach (var hardInfo in searcher.Get()) {
					if (hardInfo.Properties["Name"].Value != null) {
						device_names.Add(hardInfo.Properties["Name"].Value.ToString());
					}
				}
			}
			foreach (var cpd in cpds) {
				cpd.info = device_names.First(dn => dn.Contains(cpd.id)).Replace($"({cpd.id})", "").Replace(cpd.id, "");		
			}
		}

		#region 寻找可用端口

		/// <summary>
		/// 由于这部分代码为应用层程序，因此不能被放置在CC9D代码中。
		/// </summary>
		/// <returns></returns>
		public void getAvaliablePort(IEnumerable<ComPortDesc> cpds) {
			Task[] tasks = new Task[cpds.Count()];
			int i = 0;
			foreach(var cpd in cpds) {
				tasks[i++] = Task.Run(() => {
					cpd.warning = "";
					try {
						using (var sp = new SerialPortDp(cpd.id, out cpd.warning))
						using (var test_codec = new Cc9d.Cc9dCodec(sp)) {
							sp.openPort();
							if (sp.IsRunning == false) {
								cpd.warning += "端口无法打开；";
								cpd.avaliable = false;
							} else {
								var rev = ChholCmdPort.PortChecker.check(test_codec);
								cpd.warning += rev.warning;
								cpd.avaliable = rev.avaliable;
							}
						}
					} catch (System.Exception e) {
						cpd.warning += $"{e.Message}";
						cpd.avaliable = false;
					}
				});
			}
			Task.WhenAll(tasks).GetAwaiter().GetResult();
			return;
		}

		#endregion




	}
}
